# -*- coding: utf-8 -*-

## author: dhs87 (@github) / dhach (@Codeplex)

## This platform-independent script is intended to convert
## the .xml-file exported by konste's (@codeplex) SPBWalletExporter
## into a format accepted by KeePass 2's xml import function

## Usage: 
## The file you want to convert has to be specified manually in
## "input file = open(file_name)"
## If it isn't located in the same folder as the script specify the path as well
##
## Note that attachments don't get imported
## Instead, a string field is added to your wallet with the file name
## Add them manually to your wallet afterwards
##
## Also note that a group named "delete_me" will be created
## This is due to KeePass's internal structure
## The group can be deleted safely

import re

## open the input file in read-only mode and create the output file
input_file = open("export_wallet.xml")
output_file = open("import_wallet.xml", "w+")

## iterate over the input_file and remove all leading whitespaces 
for line in input_file:
    line = line.lstrip(" ")

## add the needed KeePassFile identifier and the root-group, close the latter
    if re.search("<Root>", line):
        output_file.write("<KeePassFile>\n")
    line = re.sub("<Root>", "<Root>\n<Group><Name>root_group</Name>", line)
    line = re.sub("</Root>", "</Group>\n</Root>", line)
    output_file.flush()

## Transform <Category* to the corresponding <Group>
    while re.search("<Category", line):
        line = re.sub("\"", "", line)
        line = re.sub(">", "</Name>", line)
        line = re.sub("<Category Name=", "<Group><Name>", line)
        output_file.flush()

## Transform the <Card* entry to the corresponding <Entry>
## Also the former value of <Card* gets formatted
## as the needed <String><Key><Value> object
    while re.search("<Card", line):
        line = re.sub("<Card Name=\"",
                      "<Entry>\n<String>\n<Key>Title</Key>\n<Value>", line)
        line = re.sub("\">", "</Value>\n</String>", line)
        output_file.flush()

## Transform the individual Fields of the SPB Wallet
## into the corresponding <String>-block of KeePass
    while re.search("<Field", line):
        line = re.sub("Name=\"", "<Key>", line)
        line = re.sub("\" />", "</Value>\n</String>", line)
        line = re.sub("<Field ", "<String>\n", line)
        line = re.sub("Value=\"", "\n<Value>", line)
        line = re.sub("\"", "</Key>", line)
        output_file.flush()

## This is transforms the attachment-entries into normal string fields
## The file name will be the title of such a field in your wallet
    while re.search("<Attachment", line):
        line = re.sub("<Attachment FileName=\"", "<String>\n<Key>", line)
        line = re.sub("\" />", "</Key>\n<Value>This is a left-out attachment" + 
                      "</Value>\n</String>", line)
        output_file.flush()

## These two lines replace the different names SPB uses for the user entry
	line = re.sub("<Key>User</Key>", "<Key>UserName</Key>", line)
	line = re.sub("<Key>User Name</Key>", "<Key>UserName</Key>", line)
## In case you happen to have a non-English SPB Wallet
## you can use these to specify words to be replaced below these comments
## just follow the snytax:
## line = re.sub("foreign_word", "english_key_word", line)
## You have to keep the indentation aligned with the code above
## Here's an example for German:
##    line = re.sub("<Key>Passwort</Key>", "<Key>Password</Key>", line)
##    line = re.sub("<Key>Benutzer</Key>", "<Key>UserName</Key>", line)
##    line = re.sub("<Key>Hinweis</Key>", "<Key>Notes</Key>", line)
## Note that only these three key words are part of KeePass's standard template.
## Every additional replacements will be imported as string fields

## Replace closing tags not captured by the while-loops
## Write everything to file
    if re.search("</Card>", line):
        line = re.sub("</Card>", "</Entry>", line)
        output_file.flush()
    if re.search("</Category>", line):
        line = re.sub("</Category>", "</Group>", line)
        output_file.flush()
    output_file.write(line)

## close the KeePass identifier
output_file.write("\n</KeePassFile>")
output_file.flush()
